package com.lagou.factory;

import com.lagou.annotation.QjcAutowired;
import com.lagou.annotation.QjcService;
import com.lagou.annotation.QjcTransactional;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.reflections.Reflections;
import org.springframework.util.StringUtils;
import sun.reflect.Reflection;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class BeanFactory {

    // 创建一个map存储实例化后的bean
    private static Map<String, Object> map = new HashMap<>();

    static {
        try {
            // 通过反射技术扫描包，并获取反射对象集合
            Reflections reflections = new Reflections("com.lagou");
            // 获取QjcService形式的类，然后将实例化对象放入map中
            Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(QjcService.class);
            for (Class<?> clazz : typesAnnotatedWith) {
                // 获取实例化对象
                Object o = clazz.newInstance();
                QjcService qjcService = clazz.getAnnotation(QjcService.class);
                String value = qjcService.value();
                if (!StringUtils.isEmpty(value)) {
                    map.put(value, o);
                } else {
                    String[] split = clazz.getName().split("\\.");
                    map.put(split[split.length - 1], o);
                }
            }
            // 维护bean之间的依赖关系
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                Object object = entry.getValue();
                Class<?> clazz = object.getClass();
                Field[] declaredFields = clazz.getDeclaredFields();
                // 获取该类的属性
                for (Field field : declaredFields) {
                    // 判断属性是否使用了注解QjcAutowired
                    if (field.isAnnotationPresent(QjcAutowired.class) && field.getAnnotation(QjcAutowired.class).value()) {
                        // 获取属性名
                        String[] names = field.getType().getName().split("\\.");
                        String name = names[names.length - 1];
                        // 获取该类的所有方法
                        Method[] methods = clazz.getMethods();
                        for (Method method : methods) {
                            if (method.getName().equalsIgnoreCase("set" + name)) {
                                Object propertyObject = map.get(name); //其实他就是accountDao
                                // 通过反射，用set方法将属性注入
                                method.invoke(object, propertyObject);// 将accountDao注入进transferService中
                            }
                        }
                    }
                }
                // 判断该类是否使用了QjcTranscational注解，若有则使用代理对象
                if (clazz.isAnnotationPresent(QjcTransactional.class)) {
                    ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
                    // 判断该类是否实现了接口
                    Class<?>[] interfaces = clazz.getInterfaces();
                    if (interfaces != null || interfaces.length > 0) {
                        // 实现了接口用jdk动态代理
                        object = proxyFactory.getJDKProxyInstance(object);
                    } else {
                        object = proxyFactory.getCGLibProxyInstance(object);
                    }
                }
                // 将处理后的object放入map中
                map.put(entry.getKey(), object);
            }

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static Object getBean(String id) {
        return map.get(id);
    }

}
